package uy.org.softtech.cssuite.entidad.usuario;

import static uy.org.softtech.cssuite.entidad.Entidad.USUARIO_NAMESPACE;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;

import org.codehaus.jackson.map.annotate.JsonRootName;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.ForeignKey;

import uy.org.softtech.cssuite.entidad.Entidad;

/**
 * <p>Entidad que representa a un rol de usuario.</p>
 *
 * <p>El siguiente fragmento de esquema especifica el contenido esperado y representado por los atributos de esta clase.</p>
 *  
 * <pre>
 * &lt;xsd:complexType name="rol">
 *  &lt;xsd:all>
 *   &lt;xsd:element name="id" type="xsd:ID"/>
 *   &lt;xsd:element name="nombre" type="{http://cssuite.softtech.org.uy/esquemas/tipos}nombre"/>
 *   &lt;xsd:element name="comentarios" type="{http://cssuite.softtech.org.uy/esquemas/tipos}comentario" minOccurs="0"/>
 *   &lt;xsd:element name="permisos">
 *    &lt;xsd:complexType>
 *     &lt;xsd:sequence>
 *      &lt;xsd:element name="permiso" type="{http://cssuite.softtech.org.uy/esquemas/entidades}permiso" maxOccurs="unbounded" />
 *     &lt;/xsd:sequence>
 *    &lt;/xsd:complexType>
 *   &lt;/xsd:element>
 *  &lt;/xsd:all>
 * &lt;/xsd:complexType>
 * 
 * </pre>
 * 
 * @author fabian.lobo
 */
@Entity
@JsonRootName(value = "rol")
@JsonSerialize(include = Inclusion.NON_NULL)
@Table(name = "CSS_ROL")
@XmlSeeAlso({Entidad.class})
@XmlType(name = "rol", namespace = USUARIO_NAMESPACE, propOrder = {})
public class Rol extends Entidad implements Serializable {

	private static final long serialVersionUID = -1570682798992911099L;
	
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "ID_ROL")
	@XmlElement(name = "id", namespace = USUARIO_NAMESPACE, required = true)
	private Long id;
	
	@Column(name = "NOMBRE", length = 25, nullable = false)
	@XmlElement(name = "nombre", namespace = USUARIO_NAMESPACE, required = true)
	private String nombre;
	
	@Column(name = "COMENTARIOS", length = 500, nullable = true)
	@XmlElement(name = "comentarios", namespace = USUARIO_NAMESPACE, required = false)
	private String comentarios;
	
	@ManyToMany(fetch = FetchType.EAGER)
	@JoinTable(
			name = "CSS_ROL_PERMISO", 
			joinColumns = @JoinColumn(name = "ID_ROL"), 
			inverseJoinColumns = @JoinColumn(name = "ID_PERMISO")
	)
	@ForeignKey(name = "FK_ROL_PERMISO", inverseName = "FK_PERMISO_ROL")
	@Fetch(FetchMode.SUBSELECT)
	@XmlElementWrapper(name = "permisos", namespace = USUARIO_NAMESPACE, required = true)
	@XmlElement(name = "permiso", namespace = USUARIO_NAMESPACE, required = true)
	private Set<Permiso> permisos;
	
	/*
	 *  GETTERS
	 */
	public Long getId() {
		return id;
	}
	public String getNombre() {
		return nombre;
	}
	public String getComentarios() {
		return comentarios;
	}
	public Set<Permiso> getPermisos() {
		return permisos;
	}

	/*
	 *  SETTERS
	 */
	public void setId(Long id) {
		this.id = id;
	}
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	public void setComentarios(String comentarios) {
		this.comentarios = comentarios;
	}
	public void setPermisos(Set<Permiso> permisos) {
		this.permisos = permisos;
	}


	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 2;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		Rol otro = (Rol) obj;
		if (id != null && otro.id != null && id.equals(otro.id)) {
			return true;
		}
		return false;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Rol [");
		builder.append("id=" + getId() + ", ");
		builder.append("nombre=" + getNombre() + ", ");
		builder.append("comentarios=" + getComentarios());
		builder.append("]");
		return builder.toString();
	}

	@Override
	public String toString(boolean incluirColecciones) {
		StringBuilder result = new StringBuilder(toString());
		
		if(incluirColecciones) {
			int offset = result.length() - 2;
			StringBuilder builder = new StringBuilder(", ");
			builder.append("permisos=" + getPermisos());
			result.insert(offset, builder.toString());
		}	
				
		return result.toString();
	}
}